﻿//////////////////////////////////////////////////////////////////////////////
//
// Copyright © 1998-2024 Glodon Company Limited.
//
// Licensed under the MIT License
//
// Permission is hereby granted, free of charge, to any person obtaining a
// copy of this software and associated documentation files (the “Software”),
// to deal in the Software without restriction, including without limitation
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
// sell copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
//
//////////////////////////////////////////////////////////////////////////////
#include "CheckBoxGroupDefinition.h"
#include "ControlDefinition.h"
#include "GbmpNew.h"
#include "GUiBaseInterfaceEnums.h"
#include "CheckBoxGroupEvent.h"
#include "FindByIdPredicate.h"
#include "ControlDefinitionChangeEvent.h"
#include "ICheckBoxGroupHandler.h"
#include <algorithm>
#include "EnableCompileWarning_The_LAST_IncludeInCpp.h"

namespace gcmp
{
    CheckBoxDefinition::CheckBoxDefinition(const std::wstring& id, const std::wstring& caption, const std::wstring& tooltip, CheckState checkState)
        : m_pControlDefinition(NEW_AS_OWNER_PTR(ControlDefinition, id, caption, tooltip))
        , m_checkState(checkState)
        , m_pControlHandler(nullptr)
    {
    }

std::wstring CheckBoxDefinition::GetId() const
{
    return m_pControlDefinition->GetId();
}

std::wstring CheckBoxDefinition::GetCaption() const
{
    return m_pControlDefinition->GetCaption();
}

std::wstring CheckBoxDefinition::GetTooltip() const
{
    return m_pControlDefinition->GetTooltip();
}

CheckState CheckBoxDefinition::GetCheckState() const
{
    return m_checkState;
}

bool CheckBoxDefinition::IsVisible() const
{
    if (m_pControlHandler)
    {
        return m_pControlHandler->IsVisible(GetId());
    }
    return m_pControlDefinition->IsVisible();
}

bool CheckBoxDefinition::IsEnabled() const
{
    if (m_pControlHandler)
    {
        return m_pControlHandler->IsEnabled(GetId());
    }
    return m_pControlDefinition->IsEnabled();
}

bool CheckBoxDefinition::SetEnabled(bool enabled)
{
    return m_pControlDefinition->SetEnabled(enabled);
}

bool CheckBoxDefinition::SetVisible(bool visible)
{
    return m_pControlDefinition->SetVisible(visible);
}

bool CheckBoxDefinition::SetControlHandler(const ICheckBoxGroupHandler* pControlHandler)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pControlHandler, L"pControlHandler为空",L"GDMPLab",L"2024-03-30");
    m_pControlHandler = const_cast<ICheckBoxGroupHandler*>(pControlHandler);
    return true;
}

bool CheckBoxDefinition::BlockControlHandler(bool needBlock)
{
    return false;
}

CheckBoxGroupDefinition::CheckBoxGroupDefinition(const std::wstring& id, const std::wstring& caption)
    : m_pBasicControlDefinition(NEW_AS_OWNER_PTR(ControlDefinition, id, caption, caption))
{
    m_pDefinitionChangeEvent = NEW_AS_OWNER_PTR(ControlDefinitionChangeEvent, L"ControlDefinitionChangeEvent", this);
    m_pCheckBoxGroupEvent = NEW_AS_OWNER_PTR(CheckBoxGroupEvent, L"CheckBoxGroupEvent", this);
}

CheckBoxGroupDefinition::~CheckBoxGroupDefinition()
{
}

std::wstring CheckBoxGroupDefinition::GetId() const
{
    return m_pBasicControlDefinition->GetId();
}

std::wstring CheckBoxGroupDefinition::GetCaption() const
{
    return m_pBasicControlDefinition->GetCaption();
}

std::wstring CheckBoxGroupDefinition::GetTooltip() const
{
    return m_pBasicControlDefinition->GetTooltip();
}

bool CheckBoxGroupDefinition::AddCheckBox(const std::wstring& id, const std::wstring& caption, const std::wstring& tooltip, CheckState checkState)
{
    auto search = std::find_if(m_checkBoxDefines.begin(), m_checkBoxDefines.end(), FindPtrBIdPredicate<OwnerPtr<CheckBoxDefinition>>(id));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search == m_checkBoxDefines.end(), L"CheckBoxGroup内CheckBox名字必须唯一",L"GDMPLab",L"2024-03-30");

    OwnerPtr<CheckBoxDefinition> pCheckBoxDefine = NEW_AS_OWNER_PTR(CheckBoxDefinition, id, caption, tooltip, checkState);
    CheckBoxDefinition* define = pCheckBoxDefine.get();
    m_checkBoxDefines.emplace_back(TransferOwnership(pCheckBoxDefine));

    ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Add);
    arguments.SetControlDefinition(define);
    m_pDefinitionChangeEvent->Emit(&arguments);
 
    return true;
}

bool CheckBoxGroupDefinition::InsertCheckBox(const std::wstring& beforeId, const std::wstring& id, const std::wstring& caption, const std::wstring& tooltip, CheckState checkState)
{
    auto search = std::find_if(m_checkBoxDefines.begin(), m_checkBoxDefines.end(), FindPtrBIdPredicate<OwnerPtr<CheckBoxDefinition>>(id));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search == m_checkBoxDefines.end(), L"CheckBoxGroup内CheckBox名字必须唯一",L"GDMPLab",L"2024-03-30");

    search = std::find_if(m_checkBoxDefines.begin(), m_checkBoxDefines.end(), FindPtrBIdPredicate<OwnerPtr<CheckBoxDefinition>>(beforeId));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search != m_checkBoxDefines.end(), L"CheckBoxGroup内没有找到插入参考的名字",L"GDMPLab",L"2024-03-30");
    
    int index = static_cast<int>(std::distance(m_checkBoxDefines.begin(), search));
    OwnerPtr<CheckBoxDefinition> pCheckBoxDefine = NEW_AS_OWNER_PTR(CheckBoxDefinition, id, caption, tooltip, checkState);

    CheckBoxDefinition* define = pCheckBoxDefine.get(); 
    m_checkBoxDefines.insert(search, TransferOwnership(pCheckBoxDefine));

    ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Insert);
    arguments.SetControlDefinition(define);
    arguments.SetDeleteOrInsertControlDefinitionIndex(index);
    m_pDefinitionChangeEvent->Emit(&arguments);

   
   
    return true;
}

bool CheckBoxGroupDefinition::DeleteCheckBox(const std::wstring& id)
{
    auto search = std::find_if(m_checkBoxDefines.begin(), m_checkBoxDefines.end(), FindPtrBIdPredicate<OwnerPtr<CheckBoxDefinition>>(id));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search != m_checkBoxDefines.end(), L"CheckBoxGroup内没找到要删除的名字",L"GDMPLab",L"2024-03-30");
    int index = static_cast<int>(std::distance(m_checkBoxDefines.begin(), search));
    m_checkBoxDefines.erase(search);
    ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Delete);
    arguments.SetDeleteOrInsertControlDefinitionIndex(index);
    m_pDefinitionChangeEvent->Emit(&arguments);
    return true;
}

void CheckBoxGroupDefinition::DeleteAllCheckBoxes()
{
    m_checkBoxDefines.clear();
    ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::DeleteAll);
    m_pDefinitionChangeEvent->Emit(&arguments);
}

std::vector<const ICheckBoxDefinition*> CheckBoxGroupDefinition::GetAllCheckBoxes() const
{
    std::vector<const ICheckBoxDefinition*> result;
    for (auto& define : m_checkBoxDefines)
        result.push_back(define.get());
    return result;
}

CheckState CheckBoxGroupDefinition::GetCheckState(const std::wstring& id, bool* pOk) const
{
    CheckState result = CheckState::Unchecked;
    auto search = std::find_if(m_checkBoxDefines.begin(), m_checkBoxDefines.end(), FindPtrBIdPredicate<OwnerPtr<CheckBoxDefinition>>(id));
    if (search != m_checkBoxDefines.end())
    {
        result = (*search)->GetCheckState();
        if (pOk)
            *pOk = true;
    }
    else
    {
        if (pOk)
            *pOk = false;
        DBG_WARN(L"CheckBoxGroup内没有要找的名字",L"GDMPLab",L"2024-03-30");
    }

    return result;
}

bool CheckBoxGroupDefinition::SetCheckState(const std::wstring& id, CheckState checkState)
{
    auto search = std::find_if(m_checkBoxDefines.begin(), m_checkBoxDefines.end(), FindPtrBIdPredicate<OwnerPtr<CheckBoxDefinition>>(id));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search != m_checkBoxDefines.end(), L"CheckBoxGroup内没有要找的名字",L"GDMPLab",L"2024-03-30");
    
    if ((*search)->m_checkState != checkState)
    {
        (*search)->m_checkState = checkState;
        ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Other);
        arguments.SetModifyControlDefinitionId(id);
        m_pDefinitionChangeEvent->Emit(&arguments);
        CheckBoxGroupEventArgs args(CheckBoxGroupEventType::CheckBoxStateChanged, id, checkState);
        args.SetStateChangeByUserFlag(ControlDefinitionChangeByUser::IsDefinitionChangeByUser(GetId()));

        CheckBoxGroupEvent* pEvent = dynamic_cast<CheckBoxGroupEvent*>(GetEvent());
        if (pEvent)
        {            
            pEvent->Emit(&args);
        }
        //DBG_WARN_AND_RETURN_FALSE_UNLESS(m_pHandler, L"CheckBoxGroup控件处理者未设置", L"GDMPLab", L"2024-03-30");
        if (m_handler)
        {
            m_handler.Process(&args);
        }
    }    
    return true;
}

ICheckBoxGroupEvent* CheckBoxGroupDefinition::GetEvent() const
{
    return const_cast<ICheckBoxGroupEvent*>(m_pCheckBoxGroupEvent.get());
}

gcmp::IControlDefinitionChangeEvent* CheckBoxGroupDefinition::GetControlDefinitionChangeEvent() const
{
    return const_cast<ControlDefinitionChangeEvent*>(m_pDefinitionChangeEvent.get());
}

bool CheckBoxGroupDefinition::IsVisible() const
{
    std::vector<const ICheckBoxDefinition*> allCheckBox = GetAllCheckBoxes();
    for (auto iter : allCheckBox)
    {
        if (iter && iter->IsVisible())
        {
            return true;
        }
    }
    return false;
}

bool CheckBoxGroupDefinition::SetEnabled(const std::wstring& id, bool enabled)
{
    auto search = std::find_if(m_checkBoxDefines.begin(), m_checkBoxDefines.end(), FindPtrBIdPredicate<OwnerPtr<CheckBoxDefinition>>(id));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search != m_checkBoxDefines.end(), L"CheckBoxGroup内没有要找的名字",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_FALSE_UNLESS((*search), L"(*search)为空",L"GDMPLab",L"2024-03-30");
    if ((*search)->IsEnabled() != enabled)
    {
        bool res = (*search)->SetEnabled(enabled);
        if (res)
        {
            ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Other);
            m_pDefinitionChangeEvent->Emit(&arguments);
            return true;
        }        
    }
    return false;
}

bool CheckBoxGroupDefinition::SetVisible(const std::wstring& id, bool visible)
{
    auto search = std::find_if(m_checkBoxDefines.begin(), m_checkBoxDefines.end(), FindPtrBIdPredicate<OwnerPtr<CheckBoxDefinition>>(id));
    DBG_WARN_AND_RETURN_FALSE_UNLESS(search != m_checkBoxDefines.end(), L"CheckBoxGroup内没有要找的名字",L"GDMPLab",L"2024-03-30");
    DBG_WARN_AND_RETURN_FALSE_UNLESS((*search), L"(*search)为空",L"GDMPLab",L"2024-03-30");
    if ((*search)->IsVisible() != visible)
    {
        bool res = (*search)->SetVisible(visible);
        if (res)//设置成功，给对应的控件发送通知
        {
            ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Other);
            m_pDefinitionChangeEvent->Emit(&arguments);
            return true;
        }
    }
    return false;
}

bool CheckBoxGroupDefinition::SetControlHandler(OwnerPtr<ICheckBoxGroupHandler> pControlHandler)
{
    DBG_WARN_AND_RETURN_FALSE_UNLESS(pControlHandler, L"pControlHandler为空",L"GDMPLab",L"2024-03-30");
    bool IsNeedEmitDefineChangeEvent = false;
    for (auto& define : m_checkBoxDefines)
    {
        bool visible = define->IsVisible();
        bool enabled = define->IsEnabled();
        define->SetControlHandler(pControlHandler.get());
        if (IsNeedEmitDefineChangeEvent)
            continue;

        if (visible != pControlHandler->IsVisible(define->GetId()) || enabled != pControlHandler->IsEnabled(define->GetId()))
        {
            IsNeedEmitDefineChangeEvent = true;
        }
    }
    if (IsNeedEmitDefineChangeEvent)
    {
        ControlDefinitionChangeEventArgs arguments(ControlDefinitionChangeEventType::Other);
        m_pDefinitionChangeEvent->Emit(&arguments);
    }
    m_handler.SetControlHandler(TransferOwnership(pControlHandler));
    return true;
}

bool CheckBoxGroupDefinition::BlockControlHandler(bool needBlock)
{
    return m_handler.BlockControlHandler(needBlock);
}

}   // end namespace gcmp
